package cn.com.landsky.camera.common.utils;


import cn.com.landsky.camera.common.hikvision.HikvisionConstant;
import cn.com.landsky.camera.common.hikvision.HikvisionEnums;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/***
 ** @category 海康平台相关api工具类(详情可以参考 ArtemisPostTest.java ...
 *  需要注意的是:平台统一网关端品(http的默认是80，https的默认是443)
 ** @author qing.yunhui
 ** @email: qingyunhui@fentuan360.com
 ** @createTime: 2018/12/26-15:07
 **/
@Slf4j
public class HikvisionUtil {

    /** 请求类型 */
    private final static String CONTENT_TYPE="application/json";

    /** 能力开放平台的网站路径 -> Api统一网关标识 */
    private static final String ARTEMIS_PATH ;

    static {
        Environment environment = (Environment) ApplicationContextHolder.getBean(Environment.class);
        ArtemisConfig.host = environment.getProperty(HikvisionConstant.HIKIVISION_ISC_HOST);
        ArtemisConfig.appKey =environment.getProperty(HikvisionConstant.HIKIVISION_ISC_APPKEY);
        ArtemisConfig.appSecret = environment.getProperty(HikvisionConstant.HIKIVISION_ISC_APPSECRET);
        ARTEMIS_PATH=environment.getProperty(HikvisionConstant.HIKIVISION_ISC_ARTEMIS);
    }

    //=================================================> 视频应用服务 start <=================================================

    /**
     * 获取监控点预览取流URL
     * @param cameraIndexCode 监控点唯一标识
     * @return 预览取流 URL
     * */
    public static String callPreviewURLs(String cameraIndexCode){
        return callPreviewURLs(cameraIndexCode,null,null,null);
    }

    /**
     * 获取监控点预览取流URL
     * @param cameraIndexCode 监控点唯一标识
     * @param protocol 取流协议
     * @return 预览取流 URL
     * */
    public static String callPreviewURLs(String cameraIndexCode,HikvisionEnums.PROTOCOL protocol){
        return callPreviewURLs(cameraIndexCode,null,protocol,null);
    }

    /**
     * 获取监控点预览取流URL
     * @param cameraIndexCode 监控点唯一标识
     * @param streamType 码流类型
     * @param protocol   取流协议
     * @param transMode 传输协议
     * @return 预览取流 URL
     * */
    public static String callPreviewURLs(String cameraIndexCode, HikvisionEnums.STREAM_TYPE streamType, HikvisionEnums.PROTOCOL protocol, HikvisionEnums.TRANS_MODE transMode){
        if(StringUtil.isEmpty(cameraIndexCode)){
            throw new RuntimeException("调用【海康视频应用服务-获取监控点预览取流URL】接口，缺失必要参数!!!");
        }
        log.info("=====================>调用【海康视频应用服务-获取监控点预览取流URL】接口，请求参数,cameraIndexCode:{},streamType:{},protocol:{},transMode:{}.",
                new Object[]{cameraIndexCode, JSONObject.toJSONString(streamType),JSONObject.toJSONString(protocol),JSONObject.toJSONString(transMode)});
        String  getCamsApi = ARTEMIS_PATH + HikvisionEnums.INTERFACE_URL.PREVIEW_URL.getKey();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("cameraIndexCode", cameraIndexCode);
        if(null!=streamType){paramMap.put("streamType",streamType.getCode());}
        buildParaMap(paramMap,null,protocol,transMode);
        String result = ArtemisHttpUtil.doPostStringArtemis(new HashMap<String, String>(2) {{put("https://", getCamsApi);}}, JSON.toJSON(paramMap).toString(), null, null, CONTENT_TYPE);
        log.info("=====================>调用【海康视频应用服务-获取监控点预览取流URL】接口，响应结果:{}",new Object[]{result});
        return result;
    }

    /**
     * 获取监控点回放取流URL
     * @param cameraIndexCode 监控点唯一标识
     * @param beginTime 开始查询时间
     * @param endTime   结束查询时间
     * @return
     * */
    public static String callPlaybackURL(String cameraIndexCode, Date beginTime, Date endTime){
        return callPlaybackURL(cameraIndexCode,DateUtil.dateToString(beginTime,DateUtil.ISO_8601_FORMAT),DateUtil.dateToString(endTime,DateUtil.ISO_8601_FORMAT));
    }

    /**
     * 获取监控点回放取流URL
     * @param cameraIndexCode 监控点唯一标识
     * @param beginTime 开始查询时间（IOS8601格式：yyyy-MM-dd’T’HH:mm:ss.SSSXXX）例如北京时间：2017-06-14T00:00:00.000+08:00
     * @param endTime   结束查询时间（IOS8601格式：yyyy-MM-dd’T’HH:mm:ss.SSSXXX）例如北京时间：2017-06-15T00:00:00.000+08:00
     * @return
     * */
    public static String callPlaybackURL(String cameraIndexCode,String beginTime,String endTime){
        return callPlaybackURL(cameraIndexCode,beginTime,endTime,null,null,null,null);
    }

    /**
     * 获取监控点回放取流URL
     * @param cameraIndexCode 监控点唯一标识
     * @param beginTime 开始查询时间（IOS8601格式：yyyy-MM-dd’T’HH:mm:ss.SSSXXX）例如北京时间：2017-06-14T00:00:00.000+08:00
     * @param endTime   结束查询时间（IOS8601格式：yyyy-MM-dd’T’HH:mm:ss.SSSXXX）例如北京时间：2017-06-15T00:00:00.000+08:00
     * @param protocol
     * @return
     * */
    public static String callPlaybackURL(String cameraIndexCode,String beginTime,String endTime,HikvisionEnums.PROTOCOL protocol){
        return callPlaybackURL(cameraIndexCode,beginTime,endTime,null,protocol,null,null);
    }

    /**
     * 获取监控点回放取流URL
     * @param cameraIndexCode 监控点唯一标识
     * @param beginTime 开始查询时间（IOS8601格式：yyyy-MM-dd’T’HH:mm:ss.SSSXXX）例如北京时间：2017-06-14T00:00:00.000+08:00
     * @param endTime   结束查询时间（IOS8601格式：yyyy-MM-dd’T’HH:mm:ss.SSSXXX）例如北京时间：2017-06-15T00:00:00.000+08:00
     * @param recordLocation 存储类型
     * @param protocol 取流协议
     * @param transMode 传输协议
     * @param uuid 分页查询id(上一次查询返回的uuid，用于继续查询剩余片段，默认为空字符串)
     * @return
     * */
    public static String callPlaybackURL(String cameraIndexCode,String beginTime,String endTime,HikvisionEnums.RECORD_LOCATION recordLocation,HikvisionEnums.PROTOCOL protocol,HikvisionEnums.TRANS_MODE transMode,String uuid){
        if(StringUtil.isEmptys(cameraIndexCode,beginTime,endTime)){
            throw new RuntimeException("调用【海康视频应用服务-获取监控点回放取流URL】接口，缺失必要参数!!!");
        }
        log.info("=====================>调用【海康视频应用服务-获取监控点回放取流URL】接口，请求参数,cameraIndexCode:{},beginTime:{},endTime:{},recordLocation:{},protocol:{},transMode:{},uuid:{}",
                new Object[]{cameraIndexCode, beginTime,endTime,JSONObject.toJSONString(recordLocation),JSONObject.toJSONString(protocol),JSONObject.toJSONString(transMode),uuid});
        String  getCamsApi = ARTEMIS_PATH + HikvisionEnums.INTERFACE_URL.PREVIEW_URL.getKey();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("cameraIndexCode", cameraIndexCode);
        paramMap.put("beginTime",beginTime);
        paramMap.put("endTime",endTime);
        buildParaMap(paramMap,recordLocation,protocol,transMode);
        if(!StringUtil.isEmpty(uuid)){paramMap.put("uuid",uuid);}
        String result = ArtemisHttpUtil.doPostStringArtemis(new HashMap<String, String>(2) {{put("https://", getCamsApi);}}, JSON.toJSON(paramMap).toString(), null, null, CONTENT_TYPE);
        log.info("=====================>调用【海康视频应用服务-获取监控点回放取流URL】接口，响应结果:{}",new Object[]{result});
        return result;
    }

    /**
     * 根据监控点编号进行云台操作
     * @param cameraIndexCode 监控点唯一标识
     * @param action 开始或停止操作
     * @param command 控制命令(注意:当控制命令-取值为GOTO_PRESET时，presetIndex[预置点编号]不能为空)
     * @return
     * */
    public static String callControlling(String cameraIndexCode,HikvisionEnums.ACTION action,HikvisionEnums.COMMAND command){
        return callControlling(cameraIndexCode,action,command,null,null);
    }

    /**
     * 根据监控点编号进行云台操作
     * @param cameraIndexCode 监控点唯一标识
     * @param action 开始或停止操作
     * @param command 控制命令(注意:当控制命令-取值为GOTO_PRESET时，presetIndex[预置点编号]不能为空)
     * @param speed 云台速度(取值范围为1-100，默认50),
     * @param presetIndex 预置点编号(预置点编号，整数，通常在300以内)
     * @return
     * */
    public static String callControlling(String cameraIndexCode,HikvisionEnums.ACTION action,HikvisionEnums.COMMAND command,Integer speed,Integer presetIndex){
        if(StringUtil.isEmptys(cameraIndexCode,action,command)){
            throw new RuntimeException("调用【海康视频应用服务-根据监控点编号进行云台操作】接口，缺失必要参数!!!");
        }
        log.info("=====================>调用【海康视频应用服务-根据监控点编号进行云台操作】接口，请求参数,cameraIndexCode:{},action:{},command:{},speed:{},presetIndex:{}",
                new Object[]{cameraIndexCode,JSONObject.toJSONString(action),JSONObject.toJSONString(command),speed,presetIndex});
        String  getCamsApi = ARTEMIS_PATH +HikvisionEnums.INTERFACE_URL.CONTROLLING.getKey();
        Map<String, Object> paramMap = new HashMap<>(10);
        paramMap.put("cameraIndexCode", cameraIndexCode);
        paramMap.put("action",action.getCode());
        paramMap.put("command",command.getKey());
        if(null!=speed){
            HikvisionEnums.SPEED.checkSpeed(speed);
            paramMap.put("speed",speed);
        }
        if(HikvisionEnums.COMMAND.GOTO_PRESET.getKey().equals(command.getKey()) && null==presetIndex){
            throw new RuntimeException("调用【海康视频应用服务-根据监控点编号进行云台操作】接口，控制指定为:"+command.getKey()+"时，预置编号不能为空!!!");
        }
        if(null!=presetIndex){paramMap.put("presetIndex",presetIndex);}
        String result = ArtemisHttpUtil.doPostStringArtemis(new HashMap<String, String>(2) {{put("https://", getCamsApi);}},  JSON.toJSON(paramMap).toString(), null, null, CONTENT_TYPE);
        log.info("=====================>调用【海康视频应用服务-根据监控点编号进行云台操作】接口，响应结果:{}",new Object[]{result});
        return result;
    }

    /**
     * 分页获取区域列表为例
     * @return 监控点列表
     */
    public static String callRegions(){
        String getCamsApi = ARTEMIS_PATH + HikvisionEnums.INTERFACE_URL.REGIONS.getKey();
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("pageNo", "1");
        paramMap.put("pageSize", "2");
        String body = JSON.toJSON(paramMap).toString();
        String result = ArtemisHttpUtil.doPostStringArtemis(new HashMap<String, String>(2) {{put("https://", getCamsApi);}}, body, null, null, CONTENT_TYPE);
        return result;
    }

    /**
     * 构建入参
     * @param paramMap
     * @param recordLocation
     * @param protocol
     * @param transMode
     * */
    private static void buildParaMap(Map<String, Object> paramMap,HikvisionEnums.RECORD_LOCATION recordLocation,HikvisionEnums.PROTOCOL protocol,HikvisionEnums.TRANS_MODE transMode){
        if(null!=recordLocation){paramMap.put("recordLocation",recordLocation.getCode());}
        if(null!=protocol){paramMap.put("protocol",protocol.getKey());}
        if(null!=transMode){paramMap.put("transmode",transMode.getCode());}
    }

    //=================================================> 视频应用服务 end <=================================================


    //=================================================> 事件订阅服务 start <=================================================
    /**
     * 事件订阅
     * @param eventReceiveUrl 事件接收地址
     * @param eventTypes 要订阅的事件类型
     * @return
     * */
    public static String callSubscriptionByEvent(String eventReceiveUrl,int ...eventTypes){
        String result=null;
        String getCamsApi = ARTEMIS_PATH + HikvisionEnums.INTERFACE_URL.EVENT_SUBSCRIPTION_BY_EVENT_TYPES.getKey();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("eventDest", eventReceiveUrl);
        paramMap.put("eventTypes", eventTypes);
        String body = JSON.toJSON(paramMap).toString();
        result = ArtemisHttpUtil.doPostStringArtemis(new HashMap<String, String>(2) {{put("https://", getCamsApi);}}, body, null, null, CONTENT_TYPE);
        return result;
    }

    //=================================================> 事件订阅服务 end <=================================================




}
